/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package obiekty;

import java.awt.Image;
import java.util.Iterator;
import utils.Vector2D;
import zachowania.ZachowaniaSterujace;

/**
 *Klasa reprezentująca pocisk wystrzelony z boltera gracza
 * @author test
 */
public class Pocisk extends ObiektRuchomy
{

    ZachowaniaSterujace zachowania;
    Vector2D idzDo;
    Vector2D cel;
    private long elapsedTime;

    public Pocisk(Image image, Vector2D cel, Vector2D start, Vector2D orientacja)
    {

        super(image);
        this.orientacja = orientacja;
        this.pozycja = start;
        this.setMaxSila(100.0);
        this.setMasa(0.1);
        this.setMaxPredkosc(0.7);
        this.setPredkosc(orientacja.multiple(maxPredkosc));
        idzDo = cel;
        zachowania = new ZachowaniaSterujace();
        zycie = 1;
        maxZycie = zycie;
    }

    public boolean lec()
    {
        zachowania.seekOn();
        zachowania.obstacleAvoidanceOn();
        wyliczPrzesuniecie(zachowania.calculate(this, idzDo));
        if (pozycja.subtract(idzDo).length() < 5.0)
        {
            //przesunObiekt(idzDo);
            pozycja.x = idzDo.x;
            this.zycie = 0;
            //pozycja.x = idzDo.x;
            //pozycja.y = idzDo.y;
            return true;
        }
        return false;
    }

    @Override
    public void update(long elapsedTime)
    {
        this.elapsedTime = elapsedTime;
        lec();
    }

    private void wyliczPrzesuniecie(Vector2D steeringForce)
    {
        sila = steeringForce;
        if (sila.length() != 0.0)
        {
            predkosc = predkosc.add((sila.divide(masa).multiple(elapsedTime)));
            predkosc = predkosc.cutTo(maxPredkosc);
            if (predkosc.length() > 0.001)
            {
                orientacja = predkosc.normalize();
            }
        } else
        {
            predkosc.x = 0;
            predkosc.y = 0;
        }
        Vector2D nPozycja = pozycja.add(predkosc.multiple(elapsedTime));
        ObiektRuchomy o = null;
        if (kolidujeZObiektemStalym(nPozycja))
        {
            this.zycie--;
            this.pozycja = nPozycja;
        } else if ((o = wezKolidujacyObiektRuchomy(nPozycja)) != null)
        {
            o.setZycie(o.getZycie() - 1);
            this.zycie--;
            this.pozycja = nPozycja;
        } else
        {
            this.pozycja = nPozycja;
        }


    }

    public ObiektRuchomy wezKolidujacyObiektRuchomy(Vector2D nowaPozycja)
    {

        synchronized (mapa.getObiektyRuchome())
        {
            // Sprawdzamy kolizję z potworem
            Iterator<ObiektRuchomy> i = mapa.getObiektyRuchome().iterator();
            while (i.hasNext())
            {
                ObiektRuchomy o = i.next();
                //make sure we don't check against the individual
                if (this.equals(o))
                {
                    continue;            //calculate the distance between the positions of the entities
                }
                Vector2D toEntity = nowaPozycja.subtract(o.getPozycja());

                double dist = toEntity.length();

                // jeżeli na nowej pozycji będziemy nachodzić na obiekt ruchomy to zwracamy, że jest kolizja
                double amountOfOverLap = this.getPromien() + o.getPromien() - dist;
                if (amountOfOverLap >= 0 && amountOfOverLap <= this.getPromien() + o.getPromien())
                {
                    return o;
                }
            }
        }
        return null;
    }

    public boolean kolidujeZObiektemStalym(Vector2D nowaPozycja)
    {
        synchronized (mapa.getObiektyStale())
        {
            // Sprawdzamy kolizję z obiektami
            Iterator<ObiektStaly> it = mapa.getObiektyStale().iterator();
            while (it.hasNext())
            {
                ObiektStaly o = it.next();
                Vector2D toEntity = nowaPozycja.subtract(o.getPozycja());

                double dist = toEntity.length();

                // jeżeli na nowej pozycji będziemy nachodzić na obiekt stały to zwracamy że jest kolizja
                double amountOfOverLap = this.getPromien() + o.getPromien() - dist;
                if (amountOfOverLap >= 0 && amountOfOverLap <= this.getPromien() + o.getPromien())
                {
                    return true;
                }
            }
        }


        synchronized (mapa.getMury())
        {
            //Sprawdzamy kolizję z murami
            Iterator<Mur> ite = mapa.getMury().iterator();
            while (ite.hasNext())
            {
                Mur o = ite.next();

                double a;
                double b;
                if (o.getPozycjaPoczatkowa().x - o.getPozycjaKoncowa().x == 0)
                {
                    // PIONOWY MUR
                    if (Math.abs(nowaPozycja.x - o.getPozycjaPoczatkowa().x) <= this.getPromien())
                    {
                        return true;
                    }
                } else if (o.getPozycjaPoczatkowa().y - o.getPozycjaKoncowa().y == 0)
                {
                    // POZIOMY MUR
                    if (Math.abs(nowaPozycja.y - o.getPozycjaPoczatkowa().y) <= this.getPromien())
                    {
                        return true;
                    }
                } else
                {
                    // FUNKCJA y = ax + b, gdzie a!=0 && b != 0
                    a = (o.getPozycjaPoczatkowa().y - o.getPozycjaKoncowa().y) / (o.getPozycjaPoczatkowa().x - o.getPozycjaKoncowa().x);
                    b = o.getPozycjaPoczatkowa().y - a * o.getPozycjaPoczatkowa().x;
                }
            }
        }

        return false;
    }

    public Pocisk clone()
    {
        return new Pocisk(image, cel, pozycja, orientacja);

    }
}
